package top.lshaci.learning.csv;

import cn.hutool.core.collection.CollectionUtil;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * CSV操作(导出和导入)
 */
public class CSVUtils {

    /**
     * CSV文件列分隔符
     */
    private static final String CSV_COLUMN_SEPARATOR = ",";

    /**
     * CSV文件行分隔符
     */
    private static final String CSV_ROW_SEPARATOR = "\r\n";

    /**
     * 导出CSV文件
     *
     * @param file csv文件(路径+文件名)，csv文件不存在会自动创建
     * @param dataList 数据
     * @return
     */
    public static boolean exportCsv(File file, List<String> dataList){
        boolean isSuccess=false;

        FileOutputStream out=null;
        OutputStreamWriter osw=null;
        BufferedWriter bw=null;
        try {
            out = new FileOutputStream(file);
            osw = new OutputStreamWriter(out);
            bw =new BufferedWriter(osw);
            if(dataList!=null && !dataList.isEmpty()){
                for(String data : dataList){
                    bw.append(data).append("\r");
                }
            }
            isSuccess = true;
        } catch (Exception e) {
            isSuccess = false;
        }finally{
            if(bw!=null){
                try {
                    bw.close();
                    bw=null;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(osw!=null){
                try {
                    osw.close();
                    osw=null;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(out!=null){
                try {
                    out.close();
                    out=null;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return isSuccess;
    }

    /**
     * 导入CSV文件
     * @param file csv文件(路径+文件)
     * @return
     */
    public static List<String> importCsv(File file){
        List<String> dataList=new ArrayList<String>();
        BufferedReader br=null;
        try {
            br = new BufferedReader(new FileReader(file));
            String line = "";
            while ((line = br.readLine()) != null) {
                dataList.add(line);
            }
        }catch (Exception e) {
        }finally{
            if(br!=null){
                try {
                    br.close();
                    br=null;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return dataList;
    }

    /**
     * 解析csv格式文件
     * 从第二行开始解析.
     *
     * @param inputStream   csv文件流
     * @param matchColName  列对应的
     * @param tClass  需要返回的类型
     * @return
     */
    public static <T> List<T> getCSVData(InputStream inputStream, String[] matchColName, Class<T> tClass) {
        InputStreamReader isr = null;
        BufferedReader br = null;
        List<T> tList = new ArrayList<>();
        try {
            isr = new InputStreamReader(inputStream, "UTF-8");
            br = new BufferedReader(isr);
            String line = null;
            int lineNum = 0;
            while ((line = br.readLine()) != null) {
                lineNum++;
                if(lineNum != 1) {
                    T t = tClass.newInstance();
                    String[] str = line.split(",");
                    for (int i = 0; i < str.length; i++) {
                        String methodName = "set" + matchColName[i].substring(0, 1).toUpperCase() + matchColName[i].substring(1);
                        tClass.getDeclaredMethod(methodName, tClass.getDeclaredField(matchColName[i]).getType()).invoke(t, new Object[]{str[i]});
                    }
                    tList.add(t);
                }
            }
            return tList;
        } catch (Exception e) {
            System.out.println("CSVUtils.getCSVData读取csv文件失败"+ e.getMessage());
        } finally {
            try {
                if (br != null) {
                    br.close();
                }
                if (isr != null) {
                    isr.close();
                }
            } catch (IOException e) {
                System.out.println("CSVUtils.getCSVData关闭文件流失败");
            }
        }
        return null;
    }

    /**
     * 对象属性map键值导出
     * @param dataList 集合数据
     * @param titles   表头部数据
     * @param keys     表内容的键值
     */
    public static String exportMapCSV(List<Map<String, Object>> dataList, String titles, String keys) throws Exception {

        // 保证线程安全
        StringBuffer buf = new StringBuffer();

        String[] titleArr = null;
        String[] keyArr = null;

        titleArr = titles.split(",");
        keyArr = keys.split(",");

        // 组装表头
        for (String title : titleArr) {
            buf.append(title).append(CSV_COLUMN_SEPARATOR);
        }
        buf.append(CSV_ROW_SEPARATOR);

        // 组装数据
        if (CollectionUtil.isNotEmpty(dataList)) {
            for (Map<String, Object> data : dataList) {
                for (String key : keyArr) {
                    buf.append(data.get(key)).append(CSV_COLUMN_SEPARATOR);
                }
                buf.append(CSV_ROW_SEPARATOR);
            }
        }

        return buf.toString();
    }

    /**
     * 浏览器导出CSV文件
     * @param dataList 集合数据
     * @param response 响应
     */
    public static void exportCSV(String fileName, List<String> dataList, HttpServletResponse response) throws Exception {
        //设置Header
        responseSetProperties(fileName,response);

        //StringBuffer线程安全
        StringBuffer buf = new StringBuffer();
        ServletOutputStream os = response.getOutputStream();

        // 组装数据
        if (CollectionUtil.isNotEmpty(dataList)) {
            for (String data : dataList) {
                buf.append(data).append(CSV_COLUMN_SEPARATOR);
                buf.append(CSV_ROW_SEPARATOR);
            }
        }

        // 写出响应
        os.write(buf.toString().getBytes("UTF-8"));
        os.flush();
    }

    /**
     * 设置Header
     * @param fileName
     * @param response
     * @throws UnsupportedEncodingException
     */
    public static void responseSetProperties(String fileName, HttpServletResponse response) throws UnsupportedEncodingException {
        // 设置文件后缀
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        String fn = fileName + sdf.format(new Date()) + ".csv";
        // 读取字符编码
        String utf = "UTF-8";

        // 设置响应
        response.setContentType("application/ms-txt.numberformat:@");
        response.setCharacterEncoding(utf);
        response.setHeader("Pragma", "public");
        response.setHeader("Cache-Control", "max-age=30");
        response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fn, utf));
    }

    public static void main(String[] args) {
        List<String> dataList=new ArrayList<String>();
        dataList.add("1,张三,男");
        dataList.add("2,李四,男");
        dataList.add("3,小红,女");
        boolean isSuccess = CSVUtils.exportCsv(new File("E:/test/test.csv"), dataList);
        System.out.println(isSuccess);
    }

}
